﻿using Microsoft.AspNetCore.Mvc;
using Entity;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Newtonsoft.Json;
using IService;
using NPOI.HSSF.UserModel;
using System.Data.Common;
using System.Data;
using System.Text;
using XingWeiDaWMSProject.IService;

namespace XingWeiDaWMSProject.Controllers
{
    public class TransferOrderController : BaseController
    {
        private readonly ITransferOrderService _transferOrderService;
        private readonly IWarehouseService _warehouseService;
        private readonly ISysOrgUserManagementService _sysOrgUserService;
        private readonly INumberingRuleService _numberingRuleService;
        private readonly IProductInformationService _productService;
        private readonly IInventoryService _inventoryService;
        private readonly ILogger<TransferOrderController> _logger;
        private readonly DbConnection _dbConnection;

        public TransferOrderController(
            ITransferOrderService transferOrderService,
            IWarehouseService warehouseService,
            ISysOrgUserManagementService sysOrgUserService,
            INumberingRuleService numberingRuleService,
            IProductInformationService productService,
            ILogger<TransferOrderController> logger,
            IInventoryService inventoryService,
            DbConnection dbConnection)
        {
            _transferOrderService = transferOrderService ?? throw new ArgumentNullException(nameof(transferOrderService));
            _warehouseService = warehouseService ?? throw new ArgumentNullException(nameof(warehouseService));
            _sysOrgUserService = sysOrgUserService ?? throw new ArgumentNullException(nameof(sysOrgUserService));
            _numberingRuleService = numberingRuleService ?? throw new ArgumentNullException(nameof(numberingRuleService));
            _productService = productService ?? throw new ArgumentNullException(nameof(productService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection));
            Console.WriteLine("TransferOrderController初始化完成");
            _inventoryService = inventoryService;
        }

        #region 统一辅助方法
        private string GetCurrentUser()
        {
            var userAccount = User.Claims.FirstOrDefault(c => c.Type == "UserAccount")?.Value;
            if (string.IsNullOrEmpty(userAccount))
            {
                userAccount = HttpContext.Session.GetString("CurrentUserAccount");
                if (string.IsNullOrEmpty(userAccount))
                {
                    userAccount = User.Identity?.Name;
                    if (string.IsNullOrEmpty(userAccount))
                    {
                        Console.WriteLine("未获取到当前用户，使用默认账号");
                        userAccount = "admin";
                    }
                }
            }
            Console.WriteLine($"当前登录用户账号：{userAccount}");
            return userAccount;
        }

        private string GetDocumentStatusText(string status)
        {
            var statusMap = new Dictionary<string, string>
            {
                {"0", "草稿"}, {"1", "待审核"}, {"2", "驳回"}, {"3", "通过"}, {"4", "已完成"}
            };
            return statusMap.TryGetValue(status, out var text) ? text : $"未知({status})";
        }

        private string GetIoStatusText(string status, bool isOutbound = true)
        {
            var prefix = isOutbound ? "出库" : "入库";
            var statusMap = new Dictionary<string, string>
            {
                {"0", $"未{prefix}"}, {"1", $"部分{prefix}"}, {"2", $"已{prefix}"}
            };
            return statusMap.TryGetValue(status, out var text) ? text : $"未知({status})";
        }
        #endregion

        #region 页面跳转
        public IActionResult Index()
        {
            Console.WriteLine("进入TransferOrder/Index页面");
            return View();
        }

        public IActionResult Add()
        {
            Console.WriteLine("进入TransferOrder/Add页面（新增调拨单）");
            return View();
        }

        public IActionResult Edit(int? transferOrderId)
        {
            Console.WriteLine($"进入TransferOrder/Edit页面，调拨单ID: {transferOrderId ?? -1}");
            ViewBag.TransferOrderId = transferOrderId;
            return View();
        }

        public async Task<IActionResult> Detail(int id)
        {
            Console.WriteLine($"进入TransferOrder/Detail页面，调拨单ID: {id}");
            try
            {
                if (id <= 0)
                {
                    TempData["ErrorMsg"] = "调拨单ID无效";
                    return View();
                }

                var transferOrder = await _transferOrderService.GetTransferOrderByIdAsync(id);
                if (transferOrder == null)
                {
                    TempData["ErrorMsg"] = "未找到指定的调拨单";
                    return View();
                }

                var details = await _transferOrderService.GetTransferOrderDetailsAsync(id);
                transferOrder.details = details;
                return View(transferOrder);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Detail页面异常：{ex.Message}");
                TempData["ErrorMsg"] = "页面加载失败，请重试";
                return View();
            }
        }
        #endregion

        #region 核心数据接口
        /// <summary>
        /// 分页获取调拨单列表（修复参数传递）
        /// </summary>
        [HttpPost]
        public async Task<IActionResult> GetTransferOrders([FromForm] TransferOrderQueryParams queryParams)
        {
            _logger.LogDebug("Controller接收原始查询参数：{@QueryParams}", queryParams);
            try
            {
                // 1. 解析日期参数（含有效性校验）
                DateTime? startDate = null;
                if (!string.IsNullOrEmpty(queryParams.StartDate))
                {
                    if (DateTime.TryParse(queryParams.StartDate, out DateTime start))
                    {
                        startDate = start;
                        _logger.LogDebug("解析有效开始日期：{StartDate}", startDate.Value.ToString("yyyy-MM-dd"));
                    }
                    else
                    {
                        _logger.LogWarning("无效的开始日期格式：{InvalidStartDate}", queryParams.StartDate);
                        return Json(new { success = false, message = "开始日期格式无效（请输入yyyy-MM-dd格式）" });
                    }
                }

                DateTime? endDate = null;
                if (!string.IsNullOrEmpty(queryParams.EndDate))
                {
                    if (DateTime.TryParse(queryParams.EndDate, out DateTime end))
                    {
                        endDate = end.AddDays(1).AddTicks(-1); // 包含结束日期当天23:59:59.9999999
                        _logger.LogDebug("解析有效结束日期：{EndDate}", endDate.Value.ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    else
                    {
                        _logger.LogWarning("无效的结束日期格式：{InvalidEndDate}", queryParams.EndDate);
                        return Json(new { success = false, message = "结束日期格式无效（请输入yyyy-MM-dd格式）" });
                    }
                }

                // 2. 单据状态校验（确保仅允许有效值）
                string documentStatus = queryParams.DocumentStatus?.Trim() ?? "";
                var validDocumentStatus = new List<string> { "0", "1", "2", "3", "4" };
                if (!string.IsNullOrEmpty(documentStatus) && !validDocumentStatus.Contains(documentStatus))
                {
                    _logger.LogWarning("无效的单据状态值：{InvalidDocumentStatus}", documentStatus);
                    return Json(new { success = false, message = "单据状态仅支持：0（草稿）、1（待审核）、2（驳回）、3（通过）、4（已完成）" });
                }
                _logger.LogDebug("校验后单据状态：{DocumentStatus}", documentStatus);

                // 3. 出入库状态核心校验（匹配数据库char(1)类型）
                string ioType = queryParams.IoType?.Trim().ToLower() ?? "";
                string ioStatus = queryParams.IoStatus?.Trim() ?? "";
                var validIoTypes = new List<string> { "out", "in" };
                var validIoStatus = new List<string> { "0", "1", "2" };

                // 校验ioType有效性
                if (!string.IsNullOrWhiteSpace(ioType) && !validIoTypes.Contains(ioType))
                {
                    _logger.LogWarning("无效的出入库类型：{InvalidIoType}", ioType);
                    ioType = ""; // 重置为无效，忽略该条件
                }

                // 校验ioStatus有效性（确保是单字符）
                if (!string.IsNullOrWhiteSpace(ioStatus) && !validIoStatus.Contains(ioStatus))
                {
                    _logger.LogWarning("无效的出入库状态值：{InvalidIoStatus}", ioStatus);
                    ioStatus = ""; // 重置为无效，忽略该条件
                }

                // 最终校验：两者必须同时有效才拼接条件
                if (!string.IsNullOrWhiteSpace(ioType) && !string.IsNullOrWhiteSpace(ioStatus))
                {
                    _logger.LogDebug("校验后出入库参数：ioType={IoType}, ioStatus={IoStatus}", ioType, ioStatus);
                }
                else
                {
                    _logger.LogDebug("出入库参数无效或不完整，将忽略该条件");
                    ioType = "";
                    ioStatus = "";
                }

                // 4. 分页参数校正（避免非法值）
                int pageIndex = queryParams.PageIndex < 1 ? 1 : queryParams.PageIndex;
                int pageSize = queryParams.PageSize < 1 || queryParams.PageSize > 100 ? 10 : queryParams.PageSize;
                _logger.LogDebug("校正后分页参数：pageIndex={PageIndex}, pageSize={PageSize}", pageIndex, pageSize);

                // 5. 调用Service层查询数据
                var transferOrderList = await _transferOrderService.GetTransferOrdersAsync(
                    transnoNo: queryParams.TransnoNo?.Trim() ?? "",
                    documentStatus: documentStatus,
                    ioType: ioType,
                    ioStatus: ioStatus,
                    startDate: startDate,
                    endDate: endDate,
                    pageIndex: pageIndex,
                    pageSize: pageSize);

                // 6. 查询总记录数（条件与列表查询完全一致）
                int totalCount = await _transferOrderService.GetTransferOrdersCountAsync(
                    transnoNo: queryParams.TransnoNo?.Trim() ?? "",
                    documentStatus: documentStatus,
                    ioType: ioType,
                    ioStatus: ioStatus,
                    startDate: startDate,
                    endDate: endDate);

                _logger.LogDebug("查询完成：符合条件总记录数={TotalCount}，当前页记录数={CurrentPageCount}",
                    totalCount, transferOrderList?.Count ?? 0);

                // 7. 构造返回结果（包含状态映射）
                return Json(new
                {
                    success = true,
                    total = totalCount,
                    data = transferOrderList ?? new List<TransferOrderDTO>(),
                    documentStatusMap = new Dictionary<string, string>
            {
                {"0", "草稿"}, {"1", "待审核"}, {"2", "驳回"}, {"3", "通过"}, {"4", "已完成"}
            },
                    outboundStatusMap = new Dictionary<string, string>
            {
                {"0", "未出库"}, {"1", "部分出库"}, {"2", "已出库"}
            },
                    inboundStatusMap = new Dictionary<string, string>
            {
                {"0", "未入库"}, {"1", "部分入库"}, {"2", "已入库"}
            }
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询调拨单列表异常，原始参数：{@QueryParams}", queryParams);
                return Json(new { success = false, message = $"获取调拨单列表失败：{ex.Message}" });
            }
        }

        [HttpGet]
        public async Task<IActionResult> GetAllWarehouses()
        {
            try
            {
                var warehouses = await _warehouseService.GetAllAsync();
                var data = warehouses.Select(w => new
                {
                    warehouseId = w.warehouse_id,
                    warehouseName = w.warehouse_name
                }).ToList();
                return Json(new { success = true, data = data });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取仓库异常：{ex.Message}");
                return Json(new { success = false, message = $"获取仓库失败：{ex.Message}" });
            }
        }

        [HttpGet]
        public IActionResult GetCurrentUserInfo()
        {
            try
            {
                var userAccount = GetCurrentUser();
                return Json(new { success = true, data = new { userAccount = userAccount } });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取当前用户失败");
                return Json(new { success = false, message = "获取用户信息失败" });
            }
        }

        [HttpGet]
        public async Task<IActionResult> GetAllUsers()
        {
            try
            {
                var users = await _sysOrgUserService.GetAllOperatorsAsync();
                var data = users.Select(u => new
                {
                    userId = u.UserId,
                    userName = u.UserName,
                    userAccount = u.UserAccount,
                    departmentName = u.DepartmentName
                }).ToList();
                return Json(new { success = true, data = data });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取用户异常：{ex.Message}");
                return Json(new { success = false, message = $"获取用户失败：{ex.Message}" });
            }
        }

        [HttpPost]
        public IActionResult GenerateTransferNo()
        {
            try
            {
                string targetFormName = "调拨单";
                var rule = _numberingRuleService.GetByTargetFormName(targetFormName)
                    ?? throw new KeyNotFoundException("未配置调拨单编号规则");

                var currentUser = GetCurrentUser();
                string transferNo = _numberingRuleService.GenerateBusinessNumber(rule.rule_id, currentUser);
                return Json(new { success = true, transferNo = transferNo });
            }
            catch (KeyNotFoundException ex)
            {
                return Json(new { success = false, message = $"未找到编号规则：{ex.Message}" });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"生成单号异常：{ex.Message}");
                return Json(new { success = false, message = $"生成单号失败：{ex.Message}" });
            }
        }

        // Controllers/TransferOrderController.cs
        [HttpGet]
        public async Task<IActionResult> SearchProducts([FromQuery] ProductSearchParam param)
        {
            try
            {
                if (param.OutWarehouseId <= 0)
                    return Json(new { success = false, message = "调出仓库ID不能为空" });

                var result = await _productService.SearchWithStockAsync(
                    param.Keyword, param.OutWarehouseId,
                    param.PageNum, param.PageSize);

                return Json(new
                {
                    success = true,
                    data = new { list = result.List, total = result.Total },
                    message = "搜索成功"
                });
            }
            catch (Exception ex)
            {
                return Json(new { success = false, message = $"搜索失败：{ex.Message}" });
            }
        }
        [HttpPost]
        public async Task<IActionResult> CreateTransfer([FromBody] TransferOrderCreateDTO dto)
        {
            try
            {
                if (dto == null) return Json(new { success = false, message = "请求数据为空" });

                var validationErrors = new List<string>();
                if (string.IsNullOrEmpty(dto.transnoNo)) validationErrors.Add("调拨单号不能为空");
                if (dto.outWarehouseId <= 0) validationErrors.Add("调出仓库ID无效");
                if (dto.inWarehouseId <= 0) validationErrors.Add("调入仓库ID无效");
                if (dto.outWarehouseId == dto.inWarehouseId) validationErrors.Add("调出/调入仓库不能相同");
                if (dto.details == null || dto.details.Count == 0) validationErrors.Add("请添加调拨明细");
                else
                {
                    foreach (var detail in dto.details)
                    {
                        if (string.IsNullOrEmpty(detail.product_code)) validationErrors.Add("货品号不能为空");
                        if (detail.transfer_quantity <= 0) validationErrors.Add("调拨数量必须大于0");
                        if (detail.in_price < 0) validationErrors.Add("入库单价不能为负数");
                        if (detail.transfer_quantity * detail.in_price <= 0) validationErrors.Add("调拨金额必须大于0");
                    }
                }

                var currentUser = GetCurrentUser();
                if (string.IsNullOrEmpty(currentUser)) validationErrors.Add("未获取到当前用户");
                else
                {
                    dto.createBy = currentUser;
                    dto.updateBy = currentUser;
                    dto.createTime = DateTime.Now;
                    dto.updateTime = DateTime.Now;

                    var userInfo = await _sysOrgUserService.GetUserByAccountAsync(currentUser);
                    if (userInfo == null)
                    {
                        validationErrors.Add("未查询到当前用户的详细信息");
                    }
                    else if (string.IsNullOrEmpty(userInfo.OrganizationId.ToString()))
                    {
                        validationErrors.Add("当前用户未分配所属部门");
                    }
                    else
                    {
                        dto.organizations_id = userInfo.OrganizationId.ToString();
                    }
                }

                if (string.IsNullOrEmpty(dto.organizations_id))
                    validationErrors.Add("所属部门ID不能为空");

                if (validationErrors.Count > 0)
                    return Json(new { success = false, message = string.Join("；", validationErrors) });

                var result = await _transferOrderService.CreateTransferAsync(dto);
                return Json(new
                {
                    success = result,
                    message = result ? "创建成功" : "创建失败，请重试"
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"创建调拨单异常：{ex.Message}");
                return Json(new { success = false, message = $"创建失败：{ex.Message}" });
            }
        }

        [HttpGet]
        public async Task<IActionResult> GetLocationsByWarehouse(int warehouseId)
        {
            try
            {
                if (warehouseId <= 0)
                    return Json(new { success = false, message = "仓库ID无效" });

                var locations = await _transferOrderService.GetStorageLocationsByWarehouseAsync(warehouseId);
                return Json(new { success = true, data = locations });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取仓库位失败：{warehouseId}");
                return Json(new { success = false, message = ex.Message });
            }
        }

        [HttpPost]
        public async Task<IActionResult> ImportDetails([FromForm] IFormFile file)
        {
            try
            {
                if (file == null || file.Length == 0)
                    return Json(new { success = false, message = "请选择Excel文件" });
                if (!file.FileName.EndsWith(".xlsx") && !file.FileName.EndsWith(".xls"))
                    return Json(new { success = false, message = "仅支持.xlsx/.xls文件" });

                List<TransferOrderDetailDTO> details = new List<TransferOrderDetailDTO>();
                using (var stream = file.OpenReadStream())
                {
                    IWorkbook workbook = file.FileName.EndsWith(".xlsx") ? new XSSFWorkbook(stream) : new HSSFWorkbook(stream);
                    ISheet sheet = workbook.GetSheetAt(0);
                    if (sheet.LastRowNum < 1)
                        throw new Exception("Excel中无有效数据行");

                    for (int rowIdx = 1; rowIdx <= sheet.LastRowNum; rowIdx++)
                    {
                        IRow row = sheet.GetRow(rowIdx);
                        if (row == null) continue;

                        var productCode = GetCellValue(row.GetCell(0));
                        if (string.IsNullOrWhiteSpace(productCode))
                            throw new Exception($"第{rowIdx + 1}行：货品号不能为空");

                        var detail = new TransferOrderDetailDTO
                        {
                            product_code = productCode,
                            product_name = GetCellValue(row.GetCell(1)),
                            specification_model = GetCellValue(row.GetCell(2)),
                            product_type = GetCellValue(row.GetCell(4)),
                            transfer_quantity = int.TryParse(GetCellValue(row.GetCell(5)), out int qty) && qty > 0 ? qty :
                                throw new Exception($"第{rowIdx + 1}行：调拨数量必须大于0"),
                            in_price = decimal.TryParse(GetCellValue(row.GetCell(6)), out decimal price) && price >= 0 ? price :
                                throw new Exception($"第{rowIdx + 1}行：入库单价不能为负数")
                        };

                        detail.transfer_amount = Math.Round(detail.transfer_quantity * detail.in_price, 2);
                        if (detail.transfer_amount <= 0)
                            throw new Exception($"第{rowIdx + 1}行：调拨金额必须大于0");
                        details.Add(detail);
                    }
                }

                if (details.Count == 0)
                    return Json(new { success = false, message = "无有效数据" });

                return Json(new { success = true, message = $"导入成功，共{details.Count}条", data = details });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"导入异常：{ex.Message}");
                return Json(new { success = false, message = $"导入失败：{ex.Message}" });
            }
        }

        public class DeleteRequest
        {
            public int transferOrderId { get; set; }
        }

        [HttpPost]
        public async Task<IActionResult> Delete([FromBody] DeleteRequest request)
        {
            try
            {
                if (request.transferOrderId <= 0)
                    return Json(new { success = false, message = "调拨单ID无效" });

                var success = await _transferOrderService.DeleteAsync(request.transferOrderId);
                return Json(new
                {
                    success = success,
                    message = success ? "删除成功" : "删除失败：仅草稿/待审核/驳回状态可删除"
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"删除异常：{ex.Message}");
                return Json(new { success = false, message = $"删除失败：{ex.Message}" });
            }
        }

        [HttpPost]
        public async Task<IActionResult> BatchDelete([FromBody] List<int> ids)
        {
            try
            {
                if (ids == null || ids.Count == 0)
                    return Json(new { success = false, message = "请选择至少一条记录" });
                if (ids.Any(id => id <= 0))
                    return Json(new { success = false, message = "ID必须大于0" });

                var success = await _transferOrderService.BatchDeleteAsync(ids);
                return Json(new
                {
                    success = success,
                    message = success ? $"批量删除成功，共{ids.Count}条" : "删除失败：包含非草稿/待审核/驳回状态的单据"
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"批量删除异常：{ex.Message}");
                return Json(new { success = false, message = $"删除失败：{ex.Message}" });
            }
        }

        [HttpPost]
        public async Task<IActionResult> Cancel([FromBody] CancelRequest request)
        {
            _logger.LogInformation($"收到撤销请求：ID={request?.Id}");

            if (request == null || request.Id <= 0)
            {
                _logger.LogWarning("撤销失败：请求参数为空或ID无效");
                return Json(new { success = false, message = "调拨单ID无效（必须为正数）" });
            }

            try
            {
                var transferOrder = await _transferOrderService.GetTransferOrderByIdAsync(request.Id);
                if (transferOrder == null)
                {
                    _logger.LogWarning($"撤销失败：未找到ID={request.Id}的调拨单");
                    return Json(new { success = false, message = "未找到指定的调拨单" });
                }

                if (transferOrder.DocumentStatus == "0")
                {
                    _logger.LogInformation($"ID={request.Id}已是草稿状态，无需撤销");
                    return Json(new { success = false, message = "当前已是草稿状态，无需撤销" });
                }

                bool isApproved = new[] { "3", "4" }.Contains(transferOrder.DocumentStatus);
                if (isApproved)
                {
                    _logger.LogInformation($"ID={request.Id}为已审核状态，开始库存回滚");

                    var details = await _transferOrderService.GetTransferOrderDetailsAsync(request.Id);
                    if (details == null || details.Count == 0)
                    {
                        _logger.LogError($"ID={request.Id}无明细数据，无法回滚库存");
                        return Json(new { success = false, message = "调拨单无明细数据，无法撤销" });
                    }

                    bool rollbackSuccess = await _inventoryService.RollbackInventoryForTransfer(
                        transferOrder.OutWarehouseId,
                        transferOrder.InWarehouseId,
                        details
                    );
                    if (!rollbackSuccess)
                    {
                        _logger.LogError($"ID={request.Id}库存回滚失败");
                        return Json(new { success = false, message = "库存回滚失败，撤销终止" });
                    }
                }

                var currentUser = GetCurrentUser();
                var cancelSuccess = await _transferOrderService.CancelAsync(request.Id, currentUser);

                if (cancelSuccess)
                {
                    _logger.LogInformation($"ID={request.Id}撤销成功，操作人：{currentUser}");
                    return Json(new { success = true, message = "撤销成功，状态已重置为草稿" });
                }
                else
                {
                    _logger.LogError($"ID={request.Id}撤销操作执行失败");
                    return Json(new { success = false, message = "撤销失败，请重试" });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"ID={request.Id}撤销过程发生异常");
                return Json(new { success = false, message = $"系统异常：{ex.Message}" });
            }
        }

        public class CancelRequest
        {
            public int Id { get; set; }
        }
        #endregion

        #region 私有辅助方法
        private string GetCellValue(ICell cell)
        {
            if (cell == null) return "";
            switch (cell.CellType)
            {
                case CellType.String: return cell.StringCellValue.Trim();
                case CellType.Numeric:
                    if (DateUtil.IsCellDateFormatted(cell))
                        return ((DateTime)cell.DateCellValue).ToString("yyyy-MM-dd");
                    else
                        return cell.NumericCellValue.ToString("F0").Trim();
                case CellType.Boolean: return cell.BooleanCellValue.ToString();
                case CellType.Formula:
                    try { return cell.NumericCellValue.ToString("F0").Trim(); }
                    catch { return cell.StringCellValue.Trim(); }
                default: return "";
            }
        }
        #endregion

        #region 数据模型
        public class TransferOrderQueryParams
        {
            public string TransnoNo { get; set; }
            public string DocumentStatus { get; set; }
            public string IoStatus { get; set; }
            public string StartDate { get; set; }
            public string EndDate { get; set; }
            public int PageIndex { get; set; } = 1;
            public int PageSize { get; set; } = 10;
            public string IoType { get; set; }   // 新增：接收出入库类型（out/in）
        }

        public class ProductSearchParam
        {
            public string Keyword { get; set; }
            public int OutWarehouseId { get; set; }
            public int PageNum { get; set; } = 1;
            public int PageSize { get; set; } = 10;
            public string WarehouseName { get; set; } // 新增
        }
        #endregion

        [HttpGet]
        public async Task<IActionResult> GetTransferOrderDetail(int id)
        {
            try
            {
                if (id <= 0) return Json(new { success = false, message = "ID无效" });

                var transferOrder = await _transferOrderService.GetTransferOrderByIdAsync(id);
                if (transferOrder == null) return Json(new { success = false, message = "未找到调拨单" });

                var details = await _transferOrderService.GetTransferOrderDetailsAsync(id);
                transferOrder.details = details;
                return Json(new { success = true, data = transferOrder });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取详情异常：{ex.Message}");
                return Json(new { success = false, message = $"获取详情失败：{ex.Message}" });
            }
        }

        [HttpPost]
        public async Task<IActionResult> Audit([FromBody] BatchAuditRequest request)
        {
            Console.WriteLine($"收到审核请求：Ids={string.Join(",", request?.Ids ?? new List<int>())}, 审核结果={request?.AuditResult}");

            try
            {
                if (request == null || request.Ids == null || !request.Ids.Any())
                {
                    Console.WriteLine("审核失败：未提供调拨单ID");
                    return Json(new { success = false, message = "请选择要审核的调拨单" });
                }
                if (!new[] { "3", "2" }.Contains(request.AuditResult))
                {
                    Console.WriteLine($"审核失败：无效的审核结果={request.AuditResult}");
                    return Json(new { success = false, message = "审核结果只能是通过(3)或驳回(2)" });
                }

                var successIds = new List<int>();
                var failIds = new Dictionary<int, string>();
                var isPass = request.AuditResult == "3";

                foreach (var id in request.Ids)
                {
                    if (_dbConnection.State != ConnectionState.Open)
                        await _dbConnection.OpenAsync();

                    using (var transaction = await _dbConnection.BeginTransactionAsync())
                    {
                        try
                        {
                            Console.WriteLine($"开始处理调拨单{id}的{(isPass ? "通过" : "驳回")}审核");

                            // 调用带事务的方法（参数匹配，无CS1501错误）
                            var transferOrder = await _transferOrderService.GetTransferOrderByIdAsync(id, transaction);
                            if (transferOrder == null)
                            {
                                failIds.Add(id, "未找到该调拨单");
                                Console.WriteLine($"调拨单{id}审核失败：未找到记录");
                                continue;
                            }

                            if (transferOrder.DocumentStatus != "1")
                            {
                                string statusText = GetDocumentStatusText(transferOrder.DocumentStatus);
                                failIds.Add(id, $"当前状态为【{statusText}】，仅【待审核】可审核");
                                Console.WriteLine($"调拨单{id}审核失败：当前状态={statusText}（非待审核）");
                                continue;
                            }

                            if (isPass)
                            {
                                // 调用带事务的方法（参数匹配）
                                var details = await _transferOrderService.GetTransferOrderDetailsAsync(id, transaction);
                                if (details == null || !details.Any())
                                {
                                    failIds.Add(id, "无调拨明细，无法调整库存");
                                    Console.WriteLine($"调拨单{id}审核失败：无明细数据");
                                    continue;
                                }

                                int outWarehouseId = transferOrder.OutWarehouseId;
                                int inWarehouseId = transferOrder.InWarehouseId;
                                if (outWarehouseId <= 0 || inWarehouseId <= 0)
                                {
                                    failIds.Add(id, "调出/调入仓库ID无效");
                                    Console.WriteLine($"调拨单{id}审核失败：仓库ID无效（out={outWarehouseId}, in={inWarehouseId}）");
                                    continue;
                                }

                                bool inventoryUpdated = await _inventoryService.AdjustInventoryForTransfer(
                                    outWarehouseId, inWarehouseId, details, transaction);
                                if (!inventoryUpdated)
                                {
                                    failIds.Add(id, "库存调整失败（可能库存不足）");
                                    Console.WriteLine($"调拨单{id}审核失败：库存调整返回false");
                                    continue;
                                }
                                Console.WriteLine($"调拨单{id}库存调整成功");

                                var auditor = GetCurrentUser();
                                var auditSuccess = await _transferOrderService.AuditAsync(id, auditor, request.AuditResult, transaction);
                                if (!auditSuccess)
                                {
                                    await _inventoryService.RollbackInventoryForTransfer(outWarehouseId, inWarehouseId, details, transaction);
                                    failIds.Add(id, "审核记录保存失败");
                                    Console.WriteLine($"调拨单{id}审核失败：AuditAsync返回false");
                                    continue;
                                }
                                Console.WriteLine($"调拨单{id}审核记录保存成功");

                                await _transferOrderService.UpdateStatusAsync(id, "4", "2", "2", transaction);
                                Console.WriteLine($"调拨单{id}状态更新为已完成");
                            }
                            else
                            {
                                var auditor = GetCurrentUser();
                                var auditSuccess = await _transferOrderService.AuditAsync(id, auditor, request.AuditResult, transaction);
                                if (!auditSuccess)
                                {
                                    failIds.Add(id, "审核记录保存失败");
                                    Console.WriteLine($"调拨单{id}驳回失败：AuditAsync返回false");
                                    continue;
                                }
                                await _transferOrderService.UpdateStatusAsync(id, "2", transferOrder.OutboundStatus, transferOrder.StorageStatus, transaction);
                            }

                            await transaction.CommitAsync();
                            successIds.Add(id);
                            Console.WriteLine($"调拨单{id}审核{(isPass ? "通过" : "驳回")}成功");
                        }
                        catch (Exception ex)
                        {
                            if (transaction.Connection != null && transaction.Connection.State == ConnectionState.Open)
                            {
                                await transaction.RollbackAsync();
                            }
                            failIds.Add(id, $"系统异常：{ex.Message}");
                            Console.WriteLine($"调拨单{id}审核异常：{ex.Message}\n堆栈：{ex.StackTrace}");
                        }
                    }
                }

                var resultMsg = new StringBuilder();
                if (successIds.Count > 0)
                    resultMsg.AppendLine($"{(isPass ? "审核通过" : "审核驳回")}成功");
                if (failIds.Count > 0)
                {
                    resultMsg.AppendLine($"{(isPass ? "审核通过" : "审核驳回")}失败：");
                    foreach (var (id, msg) in failIds)
                        resultMsg.AppendLine($" - ID={id}：{msg}");
                }

                return Json(new
                {
                    success = successIds.Count > 0,
                    message = resultMsg.ToString().TrimEnd('\r', '\n'),
                    successIds = successIds,
                    failIds = failIds
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"审核接口整体异常：{ex.Message}\n堆栈：{ex.StackTrace}");
                return Json(new { success = false, message = $"审核接口异常：{ex.Message}" });
            }
        }

        public class BatchAuditRequest
        {
            public List<int> Ids { get; set; }
            public string AuditResult { get; set; } // 3=通过，2=驳回
        }

        [HttpGet]
        public async Task<IActionResult> Export(
            string transnoNo, string documentStatus, string ioStatus, string startDate, string endDate)
        {
            try
            {
                DateTime? start = null;
                if (!string.IsNullOrEmpty(startDate) && DateTime.TryParse(startDate, out DateTime s))
                    start = s;

                DateTime? end = null;
                if (!string.IsNullOrEmpty(endDate) && DateTime.TryParse(endDate, out DateTime e))
                    end = e.AddDays(1).AddTicks(-1);

                var exportData = await _transferOrderService.GetExportDataAsync(
                    transnoNo, documentStatus, ioStatus, start, end);
                if (exportData == null || exportData.Count == 0)
                    return Json(new { success = false, message = "无符合条件的数据" });

                using (var stream = new MemoryStream())
                {
                    IWorkbook workbook = new XSSFWorkbook();
                    ISheet sheet = workbook.CreateSheet("调拨单列表");

                    var headers = new List<string> {
                        "调拨单号", "单据状态", "申请日期", "调拨类型", "调出仓库", "调入仓库",
                        "出库状态", "入库状态", "调拨数量", "调拨金额", "经办人", "调拨货品",
                        "制单人", "所在部门", "制单时间", "审核人", "审核时间"
                    };
                    var headerRow = sheet.CreateRow(0);
                    for (int i = 0; i < headers.Count; i++)
                        headerRow.CreateCell(i).SetCellValue(headers[i]);

                    for (int i = 0; i < exportData.Count; i++)
                    {
                        var row = sheet.CreateRow(i + 1);
                        var data = exportData[i];
                        row.CreateCell(0).SetCellValue(data.TransnoNo);
                        row.CreateCell(1).SetCellValue(data.DocumentStatusText);
                        row.CreateCell(2).SetCellValue(data.Tfrrqdt);
                        row.CreateCell(3).SetCellValue(data.TransferType);
                        row.CreateCell(4).SetCellValue(data.OutWarehouseName);
                        row.CreateCell(5).SetCellValue(data.InWarehouseName);
                        row.CreateCell(6).SetCellValue(data.OutboundStatusText);
                        row.CreateCell(7).SetCellValue(data.StorageStatusText);
                        row.CreateCell(8).SetCellValue((double)data.TransferQuantity);
                        row.CreateCell(9).SetCellValue((double)data.TransferAmount);
                        row.CreateCell(10).SetCellValue(data.HandlerName);
                        row.CreateCell(11).SetCellValue(data.ProductName);
                        row.CreateCell(12).SetCellValue(data.MakerName);
                        row.CreateCell(13).SetCellValue(data.DepartmentName);
                        row.CreateCell(14).SetCellValue(data.CreateTime);
                        row.CreateCell(15).SetCellValue(data.ReviewerName);
                        row.CreateCell(16).SetCellValue(data.ReviewTime);
                    }

                    for (int i = 0; i < headers.Count; i++)
                    {
                        sheet.AutoSizeColumn(i);
                        if (sheet.GetColumnWidth(i) > 5000)
                            sheet.SetColumnWidth(i, 5000);
                    }

                    workbook.Write(stream);
                    stream.Position = 0;
                    var fileName = $"调拨单列表_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出调拨单失败");
                return Json(new { success = false, message = $"导出失败：{ex.Message}" });
            }
        }

        public class AuditTransferOrderRequest
        {
            public int Id { get; set; }
            public string AuditResult { get; set; } // 3=通过，2=驳回
        }
    }
}